GLOBAL_LAST_CALL = null;

function _PTJS_RPC(args,options,obj) {
  var self = new Object();

  if(typeof BASE_URL != "string") {
    throw Error("Execute requires a global BASE_URL set!")
  }
  if(typeof OUTPUT_FORMAT != "string") {
    throw Error("_PTJS_RPC requires a global OUTPUT_FORMAT set!")
  }

  self.base_url = BASE_URL
  self.sync = false;    // Default value - overridden by options['sync']
  self.debug = false;
  self.result = null;
  
  /*##############################################################
  #                            METHODS
  ##############################################################*/  
  self.DOJOcallback = function(type,data,evt) {
    self.response = {"type":type,"data":data,"evt":evt}
    switch(type) {
      case "load": 
        self.result = _PTJS_Decoder(data);
        self.runUserCallback(self.result,self)
        break;
      case "error":
        self.runUserErrorCallback(type,data,evt);
        // This may or may not get run - userErrorCallback my throw something
        self.DOJOerrorCallback(type,data,evt); 
        break;
      default: throw Error("Error in _PTJS_RPC.DOJOcallback")
    }
  }
  
  self.DOJOerrorCallback = function(type,data,evt) {
    alert("DOJOErrorCallback: " + data.message)
  }
  
  self.runUserCallback = function(arg) {
    if(self.userCallback != undefined && self.userCallback != null) {
      self.userCallback(arg,self);
    }
  }
  
  self.runUserErrorCallback = function(type,data,evt) {
    if(self.userErrorCallback != undefined && self.userErrorCallback != null) {
      self.userErrorCallback(type,data,evt);
    }
  }

  /*############################################################
  #   INIT
  ############################################################*/
  self.args = args
  self.obj = obj
  if(options && options != null) {
    if(options['cb']) self.userCallback = options['cb'];
    if(options['ecb']) self.userErrorCallback = options['ecb'];
    if(options['sync']) self.sync = options['sync'];
    if(options['debug']) self.debug = options['debug'];
  }
  self.conn = dojo.io.bind({url: self.base_url, 
                            method: 'post',
                            content: _PTJS_Encoder(self.args,self.debug),
                            handle: self.DOJOcallback,
                            sync: self.sync, 
                            mimetype: OUTPUT_FORMAT,
                            encoding: "utf-8",
                            /* TODO(dmontauk): implement timeout
                            timeoutSeconds: 10,
                            timeout: self.Timeoutcallback, */
                          });    
                        
  GLOBAL_LAST_CALL = self;
  return self;
}

function _PTJS_ModuleCaller(module,method,args,options) {
  var new_args = {};
  new_args["_PTJS_Module"] = module;
  new_args["_PTJS_Method"] = method;
  new_args["_PTJS_MethodArgs"] = args;
  return _PTJS_RPC(new_args,options);
}